use serde::{Deserialize, Serialize};
use std::env;
use config::{Config, ConfigError, Environment, File};

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AppConfig {
    pub host: String,
    pub port: u16,
    pub database_url: String,
    pub jwt_secret: String,
    pub jwt_expiration: i64,
    pub log_level: String,
    pub cors_origins: Vec<String>,
    pub upload_path: String,
    pub max_file_size: usize,
}

impl Default for AppConfig {
    fn default() -> Self {
        Self {
            host: "127.0.0.1".to_string(),
            port: 8080,
            database_url: "postgres://user:password@localhost/fm_best".to_string(),
            jwt_secret: "your-secret-key".to_string(),
            jwt_expiration: 86400, // 24 hours
            log_level: "info".to_string(),
            cors_origins: vec!["http://localhost:3000".to_string()],
            upload_path: "./uploads".to_string(),
            max_file_size: 10 * 1024 * 1024, // 10MB
        }
    }
}

impl AppConfig {
    pub fn load() -> Result<Self, ConfigError> {
        // Load .env file if it exists
        dotenvy::dotenv().ok();
        
        let mut config = Config::builder()
            .add_source(File::with_name("config/default").required(false))
            .add_source(File::with_name("config/local").required(false))
            .add_source(Environment::with_prefix("APP").separator("_"))
            .build()?;

        // Override with environment-specific config if ENV is set
        if let Ok(env) = env::var("ENV") {
            config = Config::builder()
                .add_source(config)
                .add_source(File::with_name(&format!("config/{}", env)).required(false))
                .build()?;
        }

        config.try_deserialize()
    }

    pub fn validate(&self) -> Result<(), String> {
        if self.jwt_secret.len() < 32 {
            return Err("JWT secret must be at least 32 characters long".to_string());
        }
        
        if self.port == 0 {
            return Err("Port must be greater than 0".to_string());
        }
        
        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_default_config() {
        let config = AppConfig::default();
        assert_eq!(config.host, "127.0.0.1");
        assert_eq!(config.port, 8080);
    }

    #[test]
    fn test_config_validation() {
        let mut config = AppConfig::default();
        config.jwt_secret = "short".to_string();
        assert!(config.validate().is_err());
        
        config.jwt_secret = "a-very-long-secret-key-that-is-secure".to_string();
        assert!(config.validate().is_ok());
    }
}